package com.ohos.connent.modelcloud.biz.modular.pro.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.lang.tree.parser.DefaultNodeParser;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ohos.connent.modelcloud.biz.modular.pro.entity.BizProCategory;
import com.ohos.connent.modelcloud.biz.modular.pro.entity.BizProCategoryDict;
import com.ohos.connent.modelcloud.biz.modular.pro.mapper.BizProCategoryDictMapper;
import com.ohos.connent.modelcloud.biz.modular.pro.param.BizProCategoryDictAddParam;
import com.ohos.connent.modelcloud.biz.modular.pro.param.BizProCategoryDictIdParam;
import com.ohos.connent.modelcloud.biz.modular.pro.param.BizProCategoryDictTreeParam;
import com.ohos.connent.modelcloud.biz.modular.pro.service.BizProCategoryDictService;
import com.ohos.connent.modelcloud.biz.modular.pro.service.BizProCategoryService;
import com.ohos.connent.modelcloud.common.exception.CommonException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: ChenJiaHao
 * @Date: 2024/6/4 18:43
 * @Description:
 */
@Service
public class BizProCategoryDictServiceImpl extends ServiceImpl<BizProCategoryDictMapper, BizProCategoryDict> implements BizProCategoryDictService {

    @Resource
    private BizProCategoryService bizProCategoryService;

    @Override
    public List<Tree<String>> tree(BizProCategoryDictTreeParam bizProCategoryDictTreeParam) {
        QueryWrapper<BizProCategoryDict> queryWrapper = new QueryWrapper<>();
        List<BizProCategoryDict> bizDictList = this.list(queryWrapper.lambda().orderByAsc(BizProCategoryDict::getSort));
        List<TreeNode<String>> treeNodeList = bizDictList.stream().map(bizProCategoryDict ->
                new TreeNode<>(bizProCategoryDict.getId(), bizProCategoryDict.getParentId(),
                        bizProCategoryDict.getName(), bizProCategoryDict.getLevel()).setExtra(JSONUtil.parseObj(bizProCategoryDict))).collect(Collectors.toList());
        List<Tree<String>> treeList = TreeUtil.build(treeNodeList, "0", new TreeNodeConfig().setWeightKey("level"), new DefaultNodeParser<>());
        treeMatch(treeList, bizProCategoryDictTreeParam.getSearchKey());
        return treeList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String add(BizProCategoryDictAddParam bizProCategoryAddParam) {
        checkAddParam(bizProCategoryAddParam);
        BizProCategoryDict bizProCategoryDict = BeanUtil.copyProperties(bizProCategoryAddParam, BizProCategoryDict.class).setId(IdWorker.getIdStr());
        this.save(bizProCategoryDict);
        return bizProCategoryDict.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(BizProCategoryDictIdParam bizProCategoryDictIdParam) {
        String id = bizProCategoryDictIdParam.getId();
        BizProCategoryDict bizProCategoryDict = queryEntity(id);
        // 删除子类关联的品类
        QueryWrapper<BizProCategoryDict> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BizProCategoryDict::getParentId, id).eq(BizProCategoryDict::getLevel, 3);
        List<BizProCategoryDict> bizProCategoryDicts = list(queryWrapper);
        if (CollectionUtils.isNotEmpty(bizProCategoryDicts)) {
            List<String> ids = bizProCategoryDicts.stream().map(BizProCategoryDict::getId).collect(Collectors.toList());
            bizProCategoryService.remove(Wrappers.lambdaQuery(BizProCategory.class).in(BizProCategory::getDictId, ids));
        }
        // 删除所有子节点
        if (bizProCategoryDict.getLevel() < 3) {
            remove(Wrappers.lambdaQuery(BizProCategoryDict.class).eq(BizProCategoryDict::getParentId, id));
        }
        // 删除字典
        removeById(id);
    }

    @Override
    public BizProCategoryDict queryEntity(String id) {
        BizProCategoryDict bizProCategoryDict = getById(id);
        if (ObjectUtil.isEmpty(bizProCategoryDict)) {
            throw new CommonException("品类字典不存在，id={}", id);
        }
        return bizProCategoryDict;
    }

    private void checkAddParam(BizProCategoryDictAddParam bizProCategoryAddParam) {
        String parentId = bizProCategoryAddParam.getParentId();
        BizProCategoryDict parentDict = getOne(Wrappers.lambdaQuery(BizProCategoryDict.class).eq(BizProCategoryDict::getId, parentId));
        if ("0".equals(parentId)) {
            parentDict = new BizProCategoryDict().setLevel(0);
        } else {
            if (ObjectUtil.isEmpty(parentDict)) {
                throw new CommonException("上一级品类不存在，parentId={}", parentId);
            }
        }

        Integer level = bizProCategoryAddParam.getLevel();
        if (ObjectUtil.isEmpty(level)) {
            level = parentDict.getLevel() + 1;
        } else {
            if (parentDict.getLevel() + 1 != level) {
                throw new CommonException("层级设置错误");
            }
        }
        if (level > 3) {
            throw new CommonException("当前最大只支持设置3层结构");
        }
        bizProCategoryAddParam.setLevel(level);

        BizProCategoryDict sameLevelLastDict = this.getOne(Wrappers.lambdaQuery(BizProCategoryDict.class)
                .eq(BizProCategoryDict::getParentId, parentId).orderByDesc(BizProCategoryDict::getSort).last(" limit 1 "));
        Integer sort = bizProCategoryAddParam.getSort();
        if (ObjectUtil.isEmpty(sameLevelLastDict)) {
            sort = 0;
        } else {
            if (ObjectUtil.isEmpty(sort)) {
                sort = sameLevelLastDict.getSort() + 1;
            } else {
                if (sameLevelLastDict.getSort() + 1 != sort) {
                    throw new CommonException("同层级排序设置错误，当前最大序号：{}", sameLevelLastDict.getSort());
                }
            }
            if (sameLevelLastDict.getName().equals(bizProCategoryAddParam.getName())) {
                throw new CommonException("同层级已有相同的名称：{}", sameLevelLastDict.getName());
            }
        }
        bizProCategoryAddParam.setSort(sort);
    }

    /**
     * 递归匹配所有节点
     *
     * @param treeList  树形结构
     * @param searchKey 搜索条件
     */
    public static void treeMatch(List<Tree<String>> treeList, String searchKey) {
        if (CollectionUtils.isEmpty(treeList) || ObjectUtil.isEmpty(searchKey)) {
            return;
        }
        Iterator<Tree<String>> iter = treeList.iterator();
        while (iter.hasNext()) {
            Tree<String> tree = iter.next();
            // 如果没找到，往子节点继续找
            if (!StringUtils.contains(tree.getName(), searchKey)) {
                List<Tree<String>> children = tree.getChildren();
                if (!CollectionUtils.isEmpty(children)) {
                    treeMatch(children, searchKey);
                }
                if (CollectionUtils.isEmpty(children)) {
                    iter.remove();
                }
            }
        }
    }
}
